package org.geekbang.projects.rest.client;

import org.geekbang.projects.rest.core.HttpRequest;

import javax.ws.rs.HttpMethod;
import javax.ws.rs.client.AsyncInvoker;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.InvocationCallback;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
import java.util.concurrent.Future;
import java.util.function.Function;

/**
* 默认的异步调用实现
* @author : lsq
*/
public class DefaultAsyncInvoker implements AsyncInvoker {


	private HttpRequest httpRequest;



	public DefaultAsyncInvoker(HttpRequest httpRequest){
		this.httpRequest = httpRequest;
	}

	@Override
	public Future<Response> get() {
		return createInvocation(HttpMethod.GET , null).submit();
	}

	@Override
	public <T> Future<T> get(Class<T> responseType) {
		return createInvocation(HttpMethod.GET , null).submit(responseType);
	}

	@Override
	public <T> Future<T> get(GenericType<T> responseType) {
		return createInvocation(HttpMethod.GET , null).submit(responseType);
	}

	@Override
	public <T> Future<T> get(InvocationCallback<T> callback) {
		return createInvocation(HttpMethod.GET , null).submit(callback);
	}

	/**
	 * 创建调用器
	 * @param method
	 * @return
	 */
	protected Invocation createInvocation(String method , Entity<?> entity){
		switch (method) {
			case HttpMethod.GET:
				return new HttpGetHttpInvocation(httpRequest);
			case HttpMethod.POST:
				return new HttpPostHttpInvocation(httpRequest , entity);
			case HttpMethod.PUT:
			case HttpMethod.DELETE:
		}
		return null;
	}

	@Override
	public Future<Response> post(Entity<?> entity) {
		return createInvocation(HttpMethod.POST , entity).submit();
	}

	@Override
	public <T> Future<T> post(Entity<?> entity, Class<T> responseType) {
		return createInvocation(HttpMethod.POST , entity).submit(responseType);
	}

	@Override
	public <T> Future<T> post(Entity<?> entity, GenericType<T> responseType) {
		return createInvocation(HttpMethod.POST , entity).submit(responseType);
	}

	@Override
	public <T> Future<T> post(Entity<?> entity, InvocationCallback<T> callback) {
		return createInvocation(HttpMethod.POST , entity).submit(callback);
	}

	@Override
	public Future<Response> method(String method) {
		return doExecuteMethod(method , null , invocation -> invocation.submit());
	}

	@Override
	public <T> Future<T> method(String name, Class<T> responseType) {
		return doExecuteMethod(name , null , invocation -> invocation.submit(responseType));
	}

	@Override
	public <T> Future<T> method(String name, GenericType<T> responseType) {
		return doExecuteMethod(name , null , invocation -> invocation.submit(responseType));
	}

	@Override
	public <T> Future<T> method(String name, InvocationCallback<T> callback) {
		return doExecuteMethod(name , null , invocation -> invocation.submit(callback));
	}

	@Override
	public Future<Response> method(String name, Entity<?> entity) {
		return doExecuteMethod(name , entity , invocation -> invocation.submit());
	}

	@Override
	public <T> Future<T> method(String name, Entity<?> entity, Class<T> responseType) {
		return doExecuteMethod(name , entity , invocation -> invocation.submit(responseType));
	}

	@Override
	public <T> Future<T> method(String name, Entity<?> entity, GenericType<T> responseType) {
		return doExecuteMethod(name , entity , invocation -> invocation.submit(responseType));
	}

	@Override
	public <T> Future<T> method(String name, Entity<?> entity, InvocationCallback<T> callback) {
		return doExecuteMethod(name , entity , invocation -> invocation.submit(callback));
	}



	@Override
	public Future<Response> put(Entity<?> entity) {
		return null;
	}

	@Override
	public <T> Future<T> put(Entity<?> entity, Class<T> responseType) {
		return null;
	}

	@Override
	public <T> Future<T> put(Entity<?> entity, GenericType<T> responseType) {
		return null;
	}

	@Override
	public <T> Future<T> put(Entity<?> entity, InvocationCallback<T> callback) {
		return null;
	}

	@Override
	public Future<Response> delete() {
		return null;
	}

	@Override
	public <T> Future<T> delete(Class<T> responseType) {
		return null;
	}

	@Override
	public <T> Future<T> delete(GenericType<T> responseType) {
		return null;
	}

	@Override
	public <T> Future<T> delete(InvocationCallback<T> callback) {
		return null;
	}

	@Override
	public Future<Response> head() {
		return null;
	}

	@Override
	public Future<Response> head(InvocationCallback<Response> callback) {
		return null;
	}

	@Override
	public Future<Response> options() {
		return null;
	}

	@Override
	public <T> Future<T> options(Class<T> responseType) {
		return null;
	}

	@Override
	public <T> Future<T> options(GenericType<T> responseType) {
		return null;
	}

	@Override
	public <T> Future<T> options(InvocationCallback<T> callback) {
		return null;
	}

	@Override
	public Future<Response> trace() {
		return null;
	}

	@Override
	public <T> Future<T> trace(Class<T> responseType) {
		return null;
	}

	@Override
	public <T> Future<T> trace(GenericType<T> responseType) {
		return null;
	}

	@Override
	public <T> Future<T> trace(InvocationCallback<T> callback) {
		return null;
	}

	/**
	 * 执行方法
	 * @param name 方法名称
	 * @param entity 请求实体
	 * @param function 回调对象
	 * @param <T>
	 * @return
	 */
	private <T> Future<T> doExecuteMethod(String name, Entity<?> entity , Function<Invocation , Future<T>> function){
		Invocation invocation = createInvocation(name, entity);
		if (invocation == null){
			throw new UnsupportedOperationException(String.format("未实现的异步调用操作%s" , name));
		}
		return function.apply(invocation);
	}
}
